﻿using Engine;
using Engine.Graphics;
using SharpDX;
using street.GameDllInterfaces;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.IO;
using System.Windows.Forms;

namespace WorldRacing2
{
    [ExportMetadata("Name", "World Racing 2")]
    [ExportMetadata("Version", 1)]
    [Export(typeof(street.GameDllInterfaces.IStreetAddin))]
    public class Street1Addin : street.GameDllInterfaces.IStreetAddin
    {
        #region Public Methods

        public List<IGameVertex> CreateGameVertices(SharpDX.Vector3[] middleLineCoordinates, List<Engine.Graphics.VertexStructures.MyOwnVertex.PositionNormalTextured> roadVertices, float lengthOfStreet,
            float[] middleLineDistances, float[] textureUcoordinates, DataForGamevertexCalclation data)
        {
            VertexColors colors = (VertexColors)data.gameDllData;

            List<IGameVertex> verticesWr2Data = new List<IGameVertex>(roadVertices.Count);
            float currentDistanceOnRoad = 0;

            // Colors WR2 vertices
            SharpDX.Color4 diffuseColor = new SharpDX.Color4(0.4f, 0.4f, 0.4f, 0.0f);

            System.Drawing.Color vertexColorStartRight = colors.vertexColorStartRight;
            System.Drawing.Color vertexColorStartLeft = colors.vertexColorStartLeft;
            System.Drawing.Color vertexColorEndRight = colors.vertexColorEndRight;
            System.Drawing.Color vertexColorEndLeft = colors.vertexColorEndLeft;

            // Test Colors
            // Color ColorStart = Color.Black;
            // Color ColorEnd = Color.Blue;
            // Color ColorLeft = Color.Red;
            // Color ColorRight = Color.Yellow;
            // Start

            // Left Point
            verticesWr2Data.Add(new MyOwnVertex.Wr2Data(0.0f, textureUcoordinates[0],
                0.0f, textureUcoordinates[0],
                new SharpDX.Color4((float)vertexColorEndLeft.R / 255.0f,
                    (float)vertexColorEndLeft.G / 255.0f,
                    (float)vertexColorEndLeft.B / 255.0f,
                    0), diffuseColor));

            // Middle Point
            SharpDX.Color4 mixedColor = new SharpDX.Color4((float)(vertexColorEndLeft.R + vertexColorEndRight.R) / (255.0f * 2.0f),
                (float)(vertexColorEndLeft.G + vertexColorEndRight.G) / (255.0f * 2.0f),
                (float)(vertexColorEndLeft.B + vertexColorEndRight.B) / (255.0f * 2.0f)
                , 0);

            verticesWr2Data.Add(new MyOwnVertex.Wr2Data(-0.5f, textureUcoordinates[0],
              -0.5f, textureUcoordinates[0],
              mixedColor, diffuseColor));
            // Right Point

            verticesWr2Data.Add(new MyOwnVertex.Wr2Data(-1.0f, textureUcoordinates[0], // Texture coordinates #1
                -1.0f, textureUcoordinates[0], // Texture coordinates #2
                 new SharpDX.Color4((float)vertexColorEndRight.R / 255.0f,
                    (float)vertexColorEndRight.G / 255.0f,
                    (float)vertexColorEndRight.B / 255.0f,
                    0), diffuseColor));

            // Inner
            //textureUcoordinate += middleLineDistances[0] / 100;
            for (int i = 1; i < (middleLineCoordinates.Length - 1); i++)
            {
                currentDistanceOnRoad += middleLineDistances[i - 1];
                float currentDistanceOnRoadInPercent = (currentDistanceOnRoad / lengthOfStreet);

                SharpDX.Color4 mixedColorStartEndLeft = new SharpDX.Color4()
                {
                    Alpha = 0,//(vertexColorEndLeft.A * currentDistanceOnRoadInPercent + vertexColorStartLeft.A * (1.0f - currentDistanceOnRoadInPercent)) / 255.0f,
                    Red = (vertexColorStartRight.R * currentDistanceOnRoadInPercent + vertexColorEndLeft.R * (1.0f - currentDistanceOnRoadInPercent)) / 255.0f,
                    Green = (vertexColorStartRight.G * currentDistanceOnRoadInPercent + vertexColorEndLeft.G * (1.0f - currentDistanceOnRoadInPercent)) / 255.0f,
                    Blue = (vertexColorStartRight.B * currentDistanceOnRoadInPercent + vertexColorEndLeft.B * (1.0f - currentDistanceOnRoadInPercent)) / 255.0f
                };

                SharpDX.Color4 mixedColorStartEndRight = new SharpDX.Color4()
                {
                    Alpha = 0,//(vertexColorEndRight.A * currentDistanceOnRoadInPercent + vertexColorStartRight.A * (1.0f - currentDistanceOnRoadInPercent)) / 255.0f,
                    Red = (vertexColorStartLeft.R * currentDistanceOnRoadInPercent + vertexColorEndRight.R * (1.0f - currentDistanceOnRoadInPercent)) / 255.0f,
                    Green = (vertexColorStartLeft.G * currentDistanceOnRoadInPercent + vertexColorEndRight.G * (1.0f - currentDistanceOnRoadInPercent)) / 255.0f,
                    Blue = (vertexColorStartLeft.B * currentDistanceOnRoadInPercent + vertexColorEndRight.B * (1.0f - currentDistanceOnRoadInPercent)) / 255.0f
                };

                SharpDX.Color4 mixedColorStartEndMiddle = new SharpDX.Color4()
                {
                    Alpha = 0,// (mixedColorStartEndRight.Alpha + mixedColorStartEndLeft.Alpha) / 2.0f,
                    Red = (mixedColorStartEndRight.Red + mixedColorStartEndLeft.Red) / 2.0f,
                    Green = (mixedColorStartEndRight.Green + mixedColorStartEndLeft.Green) / 2.0f,
                    Blue = (mixedColorStartEndRight.Blue + mixedColorStartEndLeft.Blue) / 2.0f,
                };

                verticesWr2Data.Add(new MyOwnVertex.Wr2Data(0.0f,
                    textureUcoordinates[i], // Texture coordinates #1
                    0.0f, textureUcoordinates[i], // Texture coordinates #2
                    mixedColorStartEndLeft// Vertex blend color
                    , diffuseColor));

                verticesWr2Data.Add(new MyOwnVertex.Wr2Data(-0.5f, textureUcoordinates[i], // Texture coordinates #1
                    -0.5f, textureUcoordinates[i], // Texture coordinates #2
                   mixedColorStartEndMiddle, diffuseColor));

                verticesWr2Data.Add(new MyOwnVertex.Wr2Data(-1.0f, textureUcoordinates[i], // Texture coordinates #1
                    -1.0f, textureUcoordinates[i], // Texture coordinates #2
                    mixedColorStartEndRight, diffuseColor));
            }

            // End
            verticesWr2Data.Add(new MyOwnVertex.Wr2Data(0.0f, textureUcoordinates[textureUcoordinates.Length - 1], // TextureCoordinates #1
            0.0f, textureUcoordinates[textureUcoordinates.Length - 1], // TextureCoordinates #2
             new SharpDX.Color4((float)vertexColorStartRight.R / 255.0f,
                (float)vertexColorStartRight.G / 255.0f,
                (float)vertexColorStartRight.B / 255.0f,
                0), diffuseColor));

            mixedColor = new SharpDX.Color4((float)(vertexColorStartRight.R + vertexColorStartLeft.R) / (255.0f * 2.0f),
                (float)(vertexColorStartRight.G + vertexColorStartLeft.G) / (255.0f * 2.0f),
                (float)(vertexColorStartRight.B + vertexColorStartLeft.B) / (255.0f * 2.0f),
                0);

            verticesWr2Data.Add(new MyOwnVertex.Wr2Data(-0.5f, textureUcoordinates[textureUcoordinates.Length - 1], // TextureCoordinates #1
                -0.5f, textureUcoordinates[textureUcoordinates.Length - 1], // TextureCoordinates #2
                 mixedColor, diffuseColor));

            verticesWr2Data.Add(new MyOwnVertex.Wr2Data(-1.0f, textureUcoordinates[textureUcoordinates.Length - 1],
                -1.0f, textureUcoordinates[textureUcoordinates.Length - 1],
                 new SharpDX.Color4((float)vertexColorStartLeft.R / 255.0f,
                    (float)vertexColorStartLeft.G / 255.0f,
                    (float)vertexColorStartLeft.B / 255.0f,
                    0), diffuseColor));

            return verticesWr2Data;
        }

        public List<IGameVertex> CreateGameVerticesForCrossroad(List<Vector3> positions, List<bool> isMainstreet)
        {
            List<IGameVertex> verticesWr2Data = new List<IGameVertex>();

            Color4 diffuseColor = new Color4()
            {
                Alpha = 1.0f,
                Red = 0.4f,
                Green = 0.4f,
                Blue = 0.4f
            };

            verticesWr2Data.Add(new MyOwnVertex.Wr2Data(
                  0.50f, 0.5f,
                  0.50f, 0.5f,
                  new Color4(0, 0, 0, 0), diffuseColor));

            for (int i = 1; i < (positions.Count - 1); i += 2)
            {
                float testU = GeoMath.DistanceBtw2Points(positions[i] + positions[0], positions[0]) / 100.0f;
                //testU = 2.0f;
                if (!isMainstreet[i])
                {
                    testU = GeoMath.DistanceBtw2Points(positions[i], positions[i + 1]) / 100.0f;

                    verticesWr2Data.Add(new MyOwnVertex.Wr2Data(
                        0.0f, testU,
                        0.0f, testU,
                        new Color4(0, 0, 0, 0), diffuseColor));

                    verticesWr2Data.Add(new MyOwnVertex.Wr2Data(
                        0.0f, -testU,
                        0.0f, -testU,
                        new Color4(0, 0, 0, 0), diffuseColor));
                }
                else
                {
                    verticesWr2Data.Add(new MyOwnVertex.Wr2Data(
                        1.0f, -testU,
                        1.0f, -testU,
                        new Color4(0, 0, 0, 0), diffuseColor));

                    verticesWr2Data.Add(new MyOwnVertex.Wr2Data(
                        0.0f, -testU,
                        0.0f, -testU,
                        new Color4(0, 0, 0, 0), diffuseColor));
                }
            }

            return verticesWr2Data;
        }

        public void CreateGameVerticesGuardRailPart1(Vector3[] middle, List<IGameVertex> verticesWr2Data, float[] textureUcoordinates)
        {
            Color4 diffuseColor = new Color4(0.4f, 0.4f, 0.4f, 0.0f);

            verticesWr2Data.Add(new MyOwnVertex.Wr2Data(textureUcoordinates[0], 0.25f,
                textureUcoordinates[0], 0.25f,
                new Color4(0, 0, 0, 0), diffuseColor));
            verticesWr2Data.Add(new MyOwnVertex.Wr2Data(textureUcoordinates[0], 1.0f,
                textureUcoordinates[0], 1.0f,
                new Color4(0, 0, 0, 0), diffuseColor));

            for (int i = 1; i < (middle.Length - 1); i++)
            {
                verticesWr2Data.Add(new MyOwnVertex.Wr2Data(textureUcoordinates[i], 0.25f,
                    textureUcoordinates[i], 0.25f,
                    new Color4(0, 0, 0, 0), diffuseColor));

                verticesWr2Data.Add(new MyOwnVertex.Wr2Data(textureUcoordinates[i], 1.0f,
                     textureUcoordinates[i], 1.0f,
                    new Color4(0, 0, 0, 0), diffuseColor));
            }

            verticesWr2Data.Add(new MyOwnVertex.Wr2Data(textureUcoordinates[textureUcoordinates.Length - 1], 0.25f,
            textureUcoordinates[textureUcoordinates.Length - 1], 0.25f,
            new Color4(0, 0, 0, 0), diffuseColor));

            verticesWr2Data.Add(new MyOwnVertex.Wr2Data(textureUcoordinates[textureUcoordinates.Length - 1], 1.0f,
                textureUcoordinates[textureUcoordinates.Length - 1], 1.0f,
                new Color4(0, 0, 0, 0), diffuseColor));
        }

        public void CreateGameVerticesGuardRailPart2(Vector3[] middle, List<IGameVertex> verticesWr2Data, float[] textureUcoordinates)
        {
            Color4 diffuseColor = new Color4(0.4f, 0.4f, 0.4f, 0.0f);

            verticesWr2Data.Add(new MyOwnVertex.Wr2Data(textureUcoordinates[0], 0.25f,
                textureUcoordinates[0], 0.25f,
                new Color4(0, 0, 0, 0), diffuseColor));
            verticesWr2Data.Add(new MyOwnVertex.Wr2Data(textureUcoordinates[0], 0.5f,
                textureUcoordinates[0], 0.5f,
                new Color4(0, 0, 0, 0), diffuseColor));

            for (int i = 1; i < (middle.Length - 1); i++)
            {
                verticesWr2Data.Add(new MyOwnVertex.Wr2Data(textureUcoordinates[i], 0.25f,
                    textureUcoordinates[i], 0.25f,
                    new Color4(0, 0, 0, 0), diffuseColor));

                verticesWr2Data.Add(new MyOwnVertex.Wr2Data(textureUcoordinates[i], 0.5f,
                    textureUcoordinates[i], 0.5f,
                    new Color4(0, 0, 0, 0), diffuseColor));
            }

            verticesWr2Data.Add(new MyOwnVertex.Wr2Data(textureUcoordinates[textureUcoordinates.Length - 1], 0.25f,
                textureUcoordinates[textureUcoordinates.Length - 1], 0.25f,
                new Color4(0, 0, 0, 0), diffuseColor));

            verticesWr2Data.Add(new MyOwnVertex.Wr2Data(textureUcoordinates[textureUcoordinates.Length - 1], 0.5f,
            textureUcoordinates[textureUcoordinates.Length - 1], 0.5f,
            new Color4(0, 0, 0, 0), diffuseColor));
        }

        public void CreateGameVerticesGuardRailPart3(Vector3[] middle, List<IGameVertex> verticesWr2Data)
        {
            Color4 diffuseColor = new Color4(0.4f, 0.4f, 0.4f, 0.0f);

            verticesWr2Data.Add(new MyOwnVertex.Wr2Data(0.5f, 0.5f,
                0.5f, 0.5f,
                new Color4(0, 0, 0, 0), diffuseColor));

            verticesWr2Data.Add(new MyOwnVertex.Wr2Data(0.5f, 0.5f,
                0.5f, 0.5f,
                new Color4(0, 0, 0, 0), diffuseColor));

            for (int i = 1; i < (middle.Length - 1); i++)
            {
                verticesWr2Data.Add(new MyOwnVertex.Wr2Data(0.5f, 0.5f,
                    0.5f, 0.5f,
                    new Color4(0, 0, 0, 0), diffuseColor));

                verticesWr2Data.Add(new MyOwnVertex.Wr2Data(0.5f, 0.6f,
                    0.5f, 0.6f,
                    new Color4(0, 0, 0, 0), diffuseColor));
            }

            verticesWr2Data.Add(new MyOwnVertex.Wr2Data(0.5f, 0.5f,
            0.5f, 0.5f,
            new Color4(0, 0, 0, 0), diffuseColor));
            verticesWr2Data.Add(new MyOwnVertex.Wr2Data(0.5f, 0.6f,
                0.5f, 0.6f,
                new Color4(0, 0, 0, 0), diffuseColor));
        }

        public street.GameDllInterfaces.IStreetAddinControl GetControlForVertices()
        {
            return new StreetAddin.Street.VertexDataControl();
        }

        public string GetGameName()
        {
            return "World Racing 2";
        }

        public DataForGamevertexCalclation ReadStreetAddinData(BinaryReader br, int Version)
        {
            switch (Version)
            {
                case 1: //
                    VertexColors colors = new VertexColors()
                    {
                        vertexColorStartLeft = System.Drawing.Color.FromArgb(br.ReadInt32()),
                        vertexColorEndRight = System.Drawing.Color.FromArgb(br.ReadInt32()),
                        vertexColorStartRight = System.Drawing.Color.FromArgb(br.ReadInt32()),
                        vertexColorEndLeft = System.Drawing.Color.FromArgb(br.ReadInt32()),
                    };
                    return new DataForGamevertexCalclation()
                    {
                        gameDllData = colors,
                        version = 1
                    };

                default:
                    VertexColors colorsDefault = new VertexColors()
                    {
                        vertexColorStartLeft = System.Drawing.Color.Red,
                        vertexColorEndLeft = System.Drawing.Color.Red,
                        vertexColorStartRight = System.Drawing.Color.Red,
                        vertexColorEndRight = System.Drawing.Color.Red
                    };
                    return new DataForGamevertexCalclation()
                    {
                        gameDllData = colorsDefault,
                        version = 1
                    };
            }
        }

        public void SaveStreetData(DataForGamevertexCalclation data, BinaryWriter bw)
        {
            //bw.Write(data.version);
            VertexColors vertexColor = (VertexColors)data.gameDllData;

            bw.Write(vertexColor.vertexColorStartLeft.ToArgb());
            bw.Write(vertexColor.vertexColorEndRight.ToArgb());
            bw.Write(vertexColor.vertexColorStartRight.ToArgb());
            bw.Write(vertexColor.vertexColorEndLeft.ToArgb());
        }
        
        #endregion Public Methods

        #region Internal Structs

        internal struct VertexColors
        {
            #region Public Fields

            public System.Drawing.Color vertexColorEndLeft;
            public System.Drawing.Color vertexColorEndRight;
            public System.Drawing.Color vertexColorStartLeft;
            public System.Drawing.Color vertexColorStartRight;

            #endregion Public Fields
        }

        #endregion Internal Structs
    }
}